#ifndef ECHO_SERVER_HPP
#define ECHO_SERVER_HPP
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstring>
#include <strings.h>
#include <cstdlib>
#include "log.hpp"
#include"inetaddr.hpp"

#define DIE(code) exit(code)
#define CONV(addr) ((struct sockaddr *)(addr))
//std::string defaultip = "127.0.0.1"; // server的默认IP地址
uint16_t defaultport = 8113;         // server的默认端口号

class UDPserver
{
public:
    UDPserver( uint16_t port = defaultport)
        :  _server(port),_sockfd(-1), _isrunning(false)
    {
    }
    void InitServer()
    {
        // 创建一个UDP socket
        _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(FATAL) << strerror(errno);
            DIE(1);
        }
        LOG(INFO) << "socket success sockfd:" << _sockfd;

        // 创建sockaddr_in对象，完成填充并绑定
        // 1.填充
        // struct sockaddr_in local;
        // bzero(&local, sizeof(local));
        // local.sin_family = AF_INET;
        // local.sin_port = htons(_port);
        // local.sin_addr.s_addr = INADDR_ANY;
        // 2.绑定
        int n = bind(_sockfd, CONV(_server.sockaddr()), _server.len());
        if (n < 0)
        {
            LOG(FATAL) << strerror(errno);
            DIE(2);
        }
        LOG(INFO) << "bind successful";
    }
    void start()
    {
        _isrunning = true;
        LOG(INFO) << "server is running";
        while (true)
        {
            char buffer[1024]; // 接收信息的缓冲区
            struct sockaddr_in clientsocket;
            socklen_t len = sizeof(clientsocket);
            
            ssize_t ret = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, CONV(&clientsocket), &len);
            if (ret == -1)
            {
                LOG(ERROR) << strerror(errno);
            }
            else if(ret>0)//说明信息接收成功
            {
                buffer[ret] = '\0';
                std::cout << "client #" << buffer << std::endl;
                std::string recallmesg = "echo @";
                recallmesg += buffer;
                ret = sendto(_sockfd, recallmesg.c_str(), recallmesg.size(), 0, CONV(&clientsocket), sizeof(clientsocket));
                if (ret == -1)
                {
                    LOG(ERROR) << strerror(errno);
                }
            }
        }
    }

private:
    int _sockfd;     // socket的文件描述符
    inetaddr _server;
    bool _isrunning; // server是否被启动
};

#endif